package services.tutor;

import models.permission.User;
import models.tutor.EnrollUnit;
import models.tutor.Theme;
import models.tutor.Tutor;
import org.apache.commons.lang.StringUtils;
import play.Logger;
import utils.query.Page;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by FireFire on 6/26 0026.
 */
public class TutorService {

    public static int pageSize = 20;

    /**
     * 得到院系信息列表
     * @return
     */
    public static List getUnits(){
        List<EnrollUnit> units = EnrollUnit.findAll();
        return units;
    }

    /**
     * 得到当前登陆的导师信息
     * @param user
     * @return
     */
    public static Tutor currentUserRelatedTutor(User user){
        return  TutorService.getTutorByCode(user.userName);
    }

    /**
     * 得到导师信息
     * @param code
     * @return
     */
    public static Tutor getTutorByCode(String code){
        Tutor tutor = Tutor.find("byStatusAndCode",true, code).first();
        //lazy load, use contents first!
        Logger.info("contents number: %s",tutor.contents.size());
        tutor.code = cypherCode(code);
        return tutor;
    }

    /**
     * 得到导师信息
     * @param code
     * @return
     */
    public static Tutor getTutorByCypheredCode(String code){
        return getTutorByCode(decypherCode(code));
    }

    /**
     * 得到人员相关主题列表信息
     * @param code
     * @return
     */
    public static List<Theme> getThemesByCode(String code){
        List<Theme> themes = Theme.find("select t from Theme t where t.individualCode is null or t.individualCode=?",decypherCode(code)).fetch();
        return themes;
    }

    /**
     * 根据院系，导师类型，当前页码返回导师列表数据
     * @param schoolName
     * @param page
     * @return
     */
    public static Page<Tutor> tutorList(String schoolName,String tutorType, int page){
        if(page<=0) page=1;
        String query = "select t from Tutor t where t.status=1 and " +
                " t.unit=? ";
        String countQuery = "select count(*) from Tutor t where t.status=1 and t.unit=? ";
        if(StringUtils.isNotEmpty(tutorType)){
            if(tutorType.equals("硕士生导师")) {
                query += " and t.isParttime=false";
                countQuery += " and t.isParttime=false";
            }
            else {
                query += " and t.tutorType=? ";
                countQuery += " and t.tutorType=? ";
            }
        }
        query += " order by t.directionCode, t.isParttime, t.name";

        List<Tutor> tutorList = new ArrayList();
        long count = 0;
        if(StringUtils.isNotEmpty(tutorType) && tutorType.equals("博士生导师")) {
            tutorList = Tutor.find(query,
                    schoolName,tutorType).fetch(page,pageSize);
            count = Tutor.count(countQuery, schoolName, tutorType);
        }else{
            tutorList = Tutor.find(query,
                    schoolName).fetch(page,pageSize);
            count = Tutor.count(countQuery, schoolName);
        }
        Page<Tutor> currentPage = new Page();
        currentPage.list = cypherTutorList(tutorList);
        currentPage.totalCount = (int)count;
        currentPage.pageSize = pageSize;
        currentPage.currPage = page;
        return currentPage;
    }

    public static Page<Tutor> tutorListByMultiple(String name, int page){
        if(page<=0) page=1;
        String searchName = "%"+name+"%";

        String query = "select t from Tutor t where t.status=1 and " +
                " t.unit like ? or t.tutorType like ? or t.name like ? order by t.directionCode, t.isParttime, t.name";

        String countQuery = "select count(*) from Tutor t where t.status=1 and " +
                " t.unit like ? or t.direction like ? or t.name like ? ";
        long count = Tutor.count(countQuery, searchName, searchName, searchName);

        List<Tutor> tutorList = Tutor.find(query,
                searchName,searchName,searchName).fetch(page,pageSize);

        Page<Tutor> currentPage = new Page();
        currentPage.list = cypherTutorList(tutorList);
        currentPage.totalCount = (int)count;
        currentPage.pageSize = pageSize;
        currentPage.currPage = page;
        return currentPage;
    }

    private static List<Tutor> cypherTutorList(List<Tutor> tutorList){
        for(int i=0; i<tutorList.size(); i++ ) {
            Tutor tutor = tutorList.get(i);
            tutor.code = cypherCode(tutor.code);
        }
        return tutorList;
    }

    public static String cypherCode(String code){
        /*
        2010000033  ->  201E0B3
          ->  2103    0EB     奇偶分离
          ->  0EB3012    反序拼接
        还可随机插入H以上字母作为扰动项，补足8位

        2005010250  ->  2B5010250   ->  25120   B005    ->  B00502152
         */
        //1, RLE
        byte digit[] = code.getBytes();
        byte repdigit = digit[0];
        int cnt = 0 ;
        StringBuffer rlecode = new StringBuffer();
        for(int i=1; i<digit.length; i++ ){
            if(digit[i] == repdigit)
                cnt++;
            else{
                if(cnt > 0){
                    rlecode.append((char)('A'+cnt));
                }
                rlecode.append((char)repdigit);
                repdigit = digit[i];
                cnt = 0;
            }
        }
        if(cnt > 0){
            rlecode.append((char)('A'+cnt));
        }
        rlecode.append((char)repdigit);

        //2, divid
        StringBuffer odd = new StringBuffer(), even = new StringBuffer();;
        for(int i=0; i<rlecode.length(); i++ ){
            if(i%2==0)
                even.append(rlecode.charAt(i));
            else
                odd.append(rlecode.charAt(i));
        }

        //3, reverse and concat
        String xcode = odd.toString() + even.reverse().toString();

        return xcode;
    }

    private static String decypherCode(String xcode){
        //1, devide
        int pivot = xcode.length()/2;
        byte odd[] = xcode.substring(0,pivot).getBytes();
        byte even[] = xcode.substring(pivot, xcode.length()).getBytes();
        int lendiff = even.length-odd.length;

        //2, reverse and concat
        StringBuffer rlecode = new StringBuffer();
        for(int i=even.length-1; i>=lendiff; i--){
            rlecode.append((char)even[i]).append((char)odd[pivot+lendiff-i-1]);
        }
        if(pivot*2 < xcode.length())
            rlecode.append((char)even[0]);

        //3, deRLE
        StringBuffer origincode = new StringBuffer();
        int rep = 0;
        for(int i=0; i<rlecode.length(); i++ ){
            char ch = rlecode.charAt(i);
            if(ch>='A')
                rep = ch-'A'+1;
            else{
                if(rep>0) {
                    for (int j = 0; j < rep; j++)
                        origincode.append(ch);
                    rep = 0;
                }
                else
                    origincode.append(ch);
            }
        }

        //Logger.info("decypherCode , %s",origincode);
        return origincode.toString();
    }
}
